#include "Utils.h"
#include <iostream>
#include <fstream>
#include <ctime>

UtilsPtr Utils::m_Instance;

Utils::Utils()
{
}

Utils::~Utils()
{
}

UtilsPtr Utils::GetInstance()
{
	if (!m_Instance)
	{
		m_Instance = UtilsPtr(new Utils());
	}
	return m_Instance;
}

ListOfEncode Utils::GetSetOfBattle()
{
	return m_setOfBattle;
}

//load data from file
void Utils::LoadFromFile()
{
	//open file to load
	std::ifstream fileIn;
	fileIn.open("data.txt");
	int size;
	unsigned int encode;
	fileIn >> size;
	for (int i=0; i< size; i++)
	{
		fileIn >> encode;
		m_setOfBattle.push_back(encode);
	}
	fileIn.close();
}//end

//intialize
void Utils::Initialize()
{
	time_t startt, endt;
	time(&startt);
	std::cout << "Init" << std::endl;

	m_setOfBattle.clear();
	m_battle = BattleShipPtr(new BattleShip());

	for (int i=0;i < MAX_H;i++)
		for (int j=0; j < MAX_V;j++)
			m_add[i][j] = 1.0f;

	m_parts[0] = PartOfBattlePtr(new PartOfBattle(false,false));
	m_parts[1] = PartOfBattlePtr(new PartOfBattle(true,false));
	m_parts[2] = PartOfBattlePtr(new PartOfBattle(false,true));
	m_parts[3] = PartOfBattlePtr(new PartOfBattle(true,true));

	//open file to load
	std::ifstream fileIn;
	fileIn.open("data.txt");
	int size,count[5][5];
	unsigned int encode;
	fileIn >> size;
	for (int i=0; i< size; i++)
	{
		fileIn >> encode;
		m_setOfBattle.push_back(encode);
		m_parts[0]->InsertPosibility(encode);
		m_parts[1]->InsertPosibility(encode);
		m_parts[2]->InsertPosibility(encode);
		m_parts[3]->InsertPosibility(encode);
	}

	for (int i=0;i<MAX_H/2;i++)
		for (int j=0;j<MAX_V/2;j++)
		{
			fileIn >> count[i][j];
		}

	time(&endt);
	std::cout << "Load done: " << difftime(endt,startt) << std::endl;


	//m_parts[0]->InsertPosibility(m_setOfBattle);
	m_parts[0]->SetCount(count);


	//m_parts[1]->InsertPosibility(m_setOfBattle);
	m_parts[1]->SetCount(count);


	//m_parts[2]->InsertPosibility(m_setOfBattle);
	m_parts[2]->SetCount(count);

	m_parts[3]->SetCount(count);
	//m_parts[3]->InsertPosibility(m_setOfBattle);

	fileIn.close();
	time(&endt);
	std::cout << "Init done" << difftime(endt,startt) << std::endl;
	//m_thread = new ThreadType(Utils::ThreadRunning);
}//end


//guess a position
Point Utils::GuessPos()
{
	//Join();
	Point result = Point(0,0);
	float max_result = 0;
	int count = 0;
	for (int i=0; i < MAX_H;i++)
		for (int j=0;j<MAX_V;j++)
		{
			Point p = Point(i,j);
			for (int k =0; k<MAX_PART;k++)
			{
				if (m_parts[k]->IsContain(p))
				{
					if (m_parts[k]->IsUnkown(p))
					{
						float newValue = m_add[i][j] * m_parts[k]->GetCount(p) / m_parts[k]->GetWeight();
						if (max_result < newValue)
						{
							max_result = newValue ;
							count = m_parts[k]->GetCount(p);
							result = p;
						}
					}
					break;
				}
			}
		}
	std::cout << "Left: " << count << std::endl;
	return result;
}//end

void Utils::ProcessPos(Point p, bool value)
{
	//Join();
	for (int i=0; i <MAX_PART;i++)
	{
		if (m_parts[i]->IsContain(p))
		{
			m_parts[i]->SetValue(p,value);
			break;
		}
	}
	m_battle->SetValue(p,value);
	// set m_add
	if (value)
	{
		for (int i=0;i<4;i++)
		{
			Point pNew (p.first+s_dx[i],p.second+s_dy[i]);
			if (BattleShip::IsInBattle(pNew))
			{
				m_add[pNew.first][pNew.second] = 100;
			}
		}
	}
	else
	{
		for (int i=0;i<4;i++)
		{
			Point pNew (p.first+s_dx[i],p.second+s_dy[i]);
			if (BattleShip::IsInBattle(pNew))
			{
				if (m_add[pNew.first][pNew.second] < 2)
				{
					m_add[pNew.first][pNew.second] *= 0.2;
				}
			}
		}
	}
}

//prepare for new set
void Utils::EndSet()
{
	Initialize();
}//end

//found a ship, process it
void Utils::FoundShip(Point p, Ship::TypeOfShip _type)
{
	ShipPtr ship = m_battle->FindShip(p,_type);
	if (ship)
	{
		//remove outside points
		PointSet pointSet = ship->GetSpaceForShip();
		PointSet::iterator ii;
		for (ii = pointSet.begin(); ii != pointSet.end(); ii++)
		{
			if (m_battle->IsUnkown(*ii))
			{
				ProcessPos(*ii,false);
			}
		}

		for (int i=0;i<4;i++)
		{
			if (!m_parts[i]->IsContainShip(ship))
			{
				m_parts[i]->RemoveShipType(_type);
			}
		}

	}
}
//end